package clever

import (
	"context"
	"gitee.com/sdynasty/clever/log"
	"net/url"
	"os"
	"time"

	"gitee.com/sdynasty/clever/registry"
	"gitee.com/sdynasty/clever/transport"
)

// Option is an application option.
type Option func(o *options)

type Mode string
const (
	// DevMode 开发模式.
	DevMode Mode = "dev"
	// BetaMode 测试模式.
	BetaMode Mode = "beta"
	// ProdMode 发布模式.
	ProdMode Mode = "prod"
)

// options is an application options.
type options struct {
	id        		string
	name      		string
	version   		string
	mode			Mode
	productId 		uint32
	privateKey 		string
	publicKey 		string
	apolloNS        string
	apolloEntity	interface{}
	redisHost 		string
	redisDB   		string
	redisAuth 		string
	metadata  		map[string]string
	endpoints 		[]*url.URL
	shutdown 		func()

	ctx  context.Context
	sigs []os.Signal

	logger			 log.Logger
	registrar        registry.Registrar
	registrarTimeout time.Duration
	servers          []transport.Server
}

// WithID with service id.
func WithID(id string) Option {
	return func(o *options) { o.id = id }
}

// WithName with service name.
func WithName(name string) Option {
	return func(o *options) { o.name = name }
}

// WithVersion with service version.
func WithVersion(version string) Option {
	return func(o *options) { o.version = version }
}

// WithMode with service name.
func WithMode(m Mode) Option {
	return func(o *options) { o.mode = m }
}

// WithProductId with service name.
func WithProductId(id uint32) Option {
	return func(o *options) {
		o.productId = id
	}
}

// WithKeys with service pem
func WithKeys(private, public string) Option {
	return func(o *options) {
		o.privateKey = private
		o.publicKey = public
	}
}

func WithShutdown(f func()) Option {
	return func(o *options) {
		o.shutdown = f
	}
}

// WithMetadata with service metadata.
func WithMetadata(md map[string]string) Option {
	return func(o *options) { o.metadata = md }
}

// WithEndpoint with service endpoint.
func WithEndpoint(endpoints ...*url.URL) Option {
	return func(o *options) { o.endpoints = endpoints }
}

// WithContext with service context.
func WithContext(ctx context.Context) Option {
	return func(o *options) { o.ctx = ctx }
}

// WithLogger with service logger.
func WithLogger(logger log.Logger) Option {
	return func(o *options) { o.logger = logger }
}

// Server transport servers.
func Server(srv ...transport.Server) Option {
	return func(o *options) {
		o.servers = append(o.servers, srv...)
	}
}

// WithSignal with exit signals.
func WithSignal(sigs ...os.Signal) Option {
	return func(o *options) { o.sigs = sigs }
}

// WithRegistrar with service registry.
func WithRegistrar(r registry.Registrar) Option {
	return func(o *options) { o.registrar = r }
}

// RegistrarTimeout with registrar timeout.
func RegistrarTimeout(t time.Duration) Option {
	return func(o *options) { o.registrarTimeout = t }
}
